package com.flying.cms.upload;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.List;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.io.IOUtils;

import com.flying.common.log.Logger;
import com.flying.common.util.Codes;
import com.flying.common.util.DateUtils;
import com.flying.common.util.MD5;
import com.flying.common.util.ServiceHelper;
import com.flying.common.util.StringUtils;
import com.flying.common.util.Utils;
import com.flying.framework.data.Data;
import com.flying.framework.service.AbstractService;

public class UploadService extends AbstractService{
	private final static Logger logger = Logger.getLogger(UploadService.class);
	
	private List<String[]> services; //in config, pattern is: moduleid|serviceName:method;moduleid|serviceName:method
	
	private List<String[]> getServices() {
		if(services != null) return services;
		
		synchronized(this) {
			if(services != null) return services;
			
			services = Utils.newArrayList();
			final String configServices = this.serviceConfig.getConfig("services");
			if(configServices == null) return services;
			
			final String[] tmps1 = StringUtils.split(configServices, ";");
			for(String s: tmps1) {
				if(s == null) continue;
				final String[] tmps2 = StringUtils.split(s, "|");
				if(tmps2.length != 2) continue;
				services.add(new String[]{tmps2[0].trim(), tmps2[1].trim()});
			}
			return services;
		}
	}
	
	public Data upload(Data request) throws Exception {
		List<FileItem> fileList = request.get("$upload.files");
		if(fileList == null || fileList.isEmpty())
			 return new Data(Codes.CODE, Codes.SUCCESS, Codes.MSG, "upload.files is empty!");
		//
		final String uploadPath = module.getModuleConfig().getConfig("uploadPath");
		//
		final List<Data> files = Utils.newArrayList();
		final Data result = new Data(Codes.CODE, Codes.SUCCESS, "x-files", files);
		for(FileItem fi: fileList) {
			final String fn 			= StringUtils.replace(fi.getName(), "\\", "/");
			final String fieldName 		= fi.getFieldName();
			final String contentType 	= fi.getContentType();
			final String uploadFilename = fn.indexOf("/") >0 ?fn.substring(fn.lastIndexOf("/") + 1): fn;
			final long size = fi.getSize();

			Date now = new Date();
			final String relationDir = DateUtils.formatDate(now, "yyyyMM") + "/" + DateUtils.formatDate(now, "dd");
			File dir = new File(uploadPath + File.separator + relationDir);
			if(!dir.exists()) dir.mkdirs();
			
			final String md5fn		   = MD5.encode(Math.random() + uploadFilename);
			final String extfn		   = uploadFilename.indexOf(".") > 0? uploadFilename.substring(uploadFilename.lastIndexOf(".") + 1):"";
			final String storeFilename = md5fn.substring(md5fn.length() - 10) + "." + extfn;
			
			//final String diskFilename = DateUtils.formatDate(now, "HHmmssms") + "." + uploadFilename;
			final String diskFilename = DateUtils.formatDate(now, "HHmmssms") + "." + storeFilename;
			final String relationPath =  relationDir + "/" + diskFilename;
			final String diskFilePath = uploadPath + "/" + relationPath;
			
			FileOutputStream fos = new FileOutputStream(diskFilePath);
			IOUtils.copy(fi.getInputStream(), fos);
			fos.close();
			//
			final Data item = new Data("x-fieldName", fieldName, "x-fileName", uploadFilename, 
					"x-relationPath", relationPath, "x-realPath", diskFilePath, 
					"x-contentType", contentType, "x-size", size, "tag", request.getString("tag"));
			files.add(item);
			logger.debug("UploadService info:" + item);
			//
			if(result.contains(fieldName)) {
				if(result.get(fieldName) instanceof String) {
					String oldPath = (String)result.get(fieldName);
					Data oldItem = (Data)result.get(fieldName+".upload$");
					
					String[] pathes = new String[]{oldPath, relationPath};
					Data[] items = new Data[]{oldItem, item};
					
					result.put(fieldName, pathes);
					result.put(fieldName+".upload$", items);
				} else {
					String[] oldPath = (String[])result.get(fieldName);
					Data[] oldItem = (Data[])result.get(fieldName+".upload$");
					
					String[] pathes = new String[oldPath.length + 1];
					Data[] items = new Data[oldItem.length + 1];
					
					System.arraycopy(oldPath, 0, pathes, 0, oldPath.length);
					System.arraycopy(oldItem, 0, items, 0, oldItem.length);
					
					pathes[pathes.length - 1] = relationPath;
					items[items.length - 1] = item;
					
					result.put(fieldName, pathes);
					result.put(fieldName+".upload$", items);
				}
			} else {
				final String urlPre = module.getModuleConfig().getConfig("uploadURL");
				result.put(fieldName, (urlPre == null?"":"") + relationPath);
				result.put(fieldName+".upload$", item);
			}
			//
			for(String[] sd: this.getServices()) {
				ServiceHelper.invokeAsync(sd[0], sd[1], item);
			}
			
		}
		return result;
	}
}
